<script setup lang="ts">
import {omit} from 'lodash'
import {computed, ref, watch, onMounted, onUnmounted, nextTick, PropType} from 'vue'
import ListTable from '@/component/list-table/ListTable.vue'
import {ColumnList, ListTableInstance} from '@/component/list-table/types.ts'

const model = defineModel<string>({default: ''})
// const props = withDefaults(defineProps<PopoverPageProps>(), {
//   pageIndex: 1,
//   pageSize: 20,
//   totalCount: 0,
//   loading: false,
//   isAuto: true,
//   width: 800,
//   trigger: 'contextmenu',
//   placement: 'bottom-start',
//   triggerKeys: () => {
//     return ['Esc']
//   }
// })
/*
* {
* "totalCount": 22,
* "pageIndex": 1,
* "pageSize": 20,
* "trigger": "contextmenu",
* "triggerKeys": [ "Esc" ],
* "placement": "bottom-start",
* "disabled": false,
*  "teleported": false,
* "width": 800,
*  "showArrow": false,
*  "persistent": false
*  }
* */
const props = defineProps({
  data: {
    type: Array as PropType<object[]>,
    required: true,
    default: () => {
      return []
    }
  },
  columnList: {
    type: Array as PropType<ColumnList>,
    required: true,
    default: () => {
      return []
    }
  },
  totalCount: {
    type: Number,
    required: true,
    default: () => {
      return 0
    }
  },
  prop: {
    type: String,
    required: true,
    default: () => {
      return ''
    }
  },
  pageIndex: {
    type: Number,
    default: () => {
      return 1
    }
  },
  isAuto: {
    type: Boolean,
    default: () => {
      return true
    }
  },
  pageSize: {
    type: Number,
    default: () => {
      return 20
    }
  },
  loading: {
    type: Boolean,
    default: () => {
      return false
    }
  },
  placeholder: {
    type: String,
    default: () => {
      return ''
    }
  },
  width: {
    type: Number,
    default: () => {
      return 800
    }
  },
  trigger: {
    type: String,
    default: () => {
      return 'click'
    }
  },
  placement: {
    type: String,
    default: () => {
      return 'bottom-start'
    }
  },
  triggerKeys: {
    type: Array as PropType<string[]>,
    default: () => {
      return ['Esc']
    }
  },
  teleported: {
    type: Boolean,
    default: () => {
      return false
    }
  },
  beforeShow: {
    type: Function
  },
  beforeHide: {
    type: Function
  }
})
const $emit = defineEmits([
    'callback',
    'change',
    'show-event',
    'hide-event',
    'current-change',
    'size-change',
    'update:pageIndex',
    'update:pageSize'
])

const visible = ref<boolean>(false)
const popoverRef = ref()
const listTableRef = ref<ListTableInstance>()
const highlightCurrentIndex = ref<number>(0)

const bind = computed(() => {
  return omit(props,
      'modelValue',
      'data',
      'columnList',
      'prop',
      'loading',
      'placeholder',
      'isAuto'
  )
})
const current = ref<number>(1)
const size = ref<number>(20)
const timeout = ref()
watch(
    () => model.value,
    (newModel, oldValue) => {
      if (newModel !== oldValue) {
        // 防抖处理
        if (timeout.value) clearTimeout(timeout.value)
        timeout.value = setTimeout(() => {
          highlightCurrentIndex.value = 0
          $emit('change', newModel)
          if (model.value && model.value !== '' && !visible.value) {
            visible.value = true
          }
        }, 500)
      }
    }
)
watch(
    () => props.data,
    () => {
      nextTick(() => {
        if (props.data && props.data.length > 0 && listTableRef.value) {
          listTableRef.value.getRef().setCurrentRow(props.data[highlightCurrentIndex.value])
        }
      })
    }
)
watch(
    () => props.pageIndex,
    () => {
      current.value = props.pageIndex
    }
)
watch(
    () => props.pageSize,
    () => {
      size.value = props.pageSize
    }
)

onMounted(() => {
  highlightCurrentIndex.value = 0
  window.addEventListener('keydown', handleKeyDown)
})
onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown)
})
const handleKeyDown = (event: any) => {
  if (props.data && props.data.length > 0) {
    const key = event.key
    console.log(key)
    if (key === 'ArrowUp' && highlightCurrentIndex.value > 0) { // 上键盘
      highlightCurrentIndex.value--
      listTableRef.value!.getRef().setCurrentRow(props.data[highlightCurrentIndex.value])
      nextTick(() => {
        scrollToHighlightRow()
      })
    } else if (key === 'ArrowDown' && (highlightCurrentIndex.value !== (props.data.length - 1))) {
      highlightCurrentIndex.value++
      listTableRef.value!.getRef().setCurrentRow(props.data[highlightCurrentIndex.value])
      nextTick(() => {
        scrollToHighlightRow()
      })
    } else if (key === 'Enter') {
      if (visible.value) {
        handleSelectChange(props.data[highlightCurrentIndex.value])
      } else {
        visible.value = true
        $emit('change')
      }
    } else if (key === 'Tab' || key === 'Escape') {
      visible.value = false
    }
  }
}
const scrollToHighlightRow = () => {
  if (!listTableRef.value) return
  // 1. 获取 el-table 的 body-wrapper（滚动容器）
  const bodyWrapper = listTableRef.value!.getRef().$el.querySelector('.el-table__body-wrapper')
  if (!bodyWrapper) return
  // 2. 找到高亮行的 DOM 节点
  const highlightRow = listTableRef.value!.getRef().$el.querySelector(`.current-row`)
  if (!highlightRow) return
  // 3. 计算目标行的位置并滚动
  const rowTop = highlightRow.offsetTop; // 行距离顶部的距离
  const rowHeight = highlightRow.clientHeight; // 行的高度
  const wrapperHeight = bodyWrapper.clientHeight; // 滚动容器的高度
  // 4. 使目标行居中显示（可选）
  listTableRef.value!.getRef().scrollTo({
    top: rowTop - (wrapperHeight / 2) + (rowHeight / 2)
  })
}

const handleCurrentChange = (val: number) => {
  highlightCurrentIndex.value = 0
  current.value = val
  $emit('update:pageIndex', current.value)
  $emit('current-change', val)
  $emit('change')
}
const handleSizeChange = (val: number) => {
  current.value = 1
  size.value = val
  $emit('update:pageIndex', current.value)
  $emit('update:pageSize', size.value)
  $emit('size-change', val)
  $emit('change')
}

const showEvent = () => {
  // $emit('show-event')
  if (props.beforeShow) {
    props.beforeShow()
  }
  document.addEventListener('click', hidePanel, false)
}
const hideEvent = () => {
  // $emit('hide-event')
  document.removeEventListener("click", hidePanel, false)
  if (props.beforeHide) {
    props.beforeHide()
    visible.value = false
  }
  nextTick(() => {
    if (timeout.value)  clearTimeout(timeout.value)
  })
}
const hidePanel = (e: any) => {
  if (!popoverRef.value.contains(e.target)) {
    visible.value = false
    hideEvent()
  }
}
const handleClickInput = () => {
  visible.value = true
  $emit('change')
  nextTick(() => {
    listTableRef.value!.getRef().setCurrentRow(props.data[highlightCurrentIndex.value])
    setTimeout(() => {
      scrollToHighlightRow()
    }, 500)
  })
}
const handleSelectChange = (row: object) => {
  if (props.data && props.data.length > 0) {
    highlightCurrentIndex.value = props.data.findIndex((v: object) => v[props.prop] === row[props.prop])
  }
  // model.value = row[props.prop]
  $emit('callback', row)
  nextTick(() => {
    if (props.isAuto) {
      visible.value = false
    }
  })
}

</script>

<template>
  <div class="popover-page-basic" ref="popoverRef">
    <el-popover
        :visible="visible"
        v-bind="Object.assign(bind, $attrs)"
        @show="showEvent"
        @hide="hideEvent"
    >
      <template #reference="scope">
        <slot name="reference" v-bind="scope">
          <el-input
              v-model="model"
              :placeholder="props.placeholder"
              clearable
              @click="handleClickInput"
          />
        </slot>
      </template>
      <div class="popover-content">
        <ListTable
            ref="listTableRef"
            :data="props.data"
            :column-list="props.columnList"
            :loading="props.loading"
            highlight-current-row
            height="200px"
            @row-dblclick="handleSelectChange"
        >
          <template v-for="(_, name) in $slots" #[name]="scope">
            <slot :name="name" v-bind="scope"/>
          </template>
        </ListTable>
        <el-pagination
            style="margin-top: 10px"
            :current-page="current"
            :page-size="size"
            :page-sizes="[10, 20, 50, 500]"
            layout="total, sizes, prev, pager, next, jumper"
            :total="props.totalCount"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
        />
      </div>
    </el-popover>
  </div>
</template>

<style scoped>
</style>